package com.easycamera.activity

import android.animation.Animator
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Point
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.RelativeLayout
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.aj.easylibrary.net.RetrofitServiceManager
import com.bumptech.glide.Glide
import com.easycamera.R
import com.easycamera.adapter.FilterAdapter
import com.easycamera.adapter.FrameAdapter
import com.easycamera.bean.FrameInfo
import com.easycamera.net.ApiService
import com.easycamera.utils.BitmapUtils
import com.seu.magicfilter.MagicEngine
import com.seu.magicfilter.filter.helper.MagicFilterType
import com.seu.magicfilter.helper.SavePictureTask
import com.seu.magicfilter.widget.MagicCameraView
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import kotlinx.android.synthetic.main.activity_camera.*
import kotlinx.android.synthetic.main.filter_layout.*
import kotlinx.android.synthetic.main.frame_layout.*
import java.io.File
import java.text.SimpleDateFormat
import java.util.*


class CameraActivity : AppCompatActivity() {
    companion object {
        const val TAG = "CameraActivity"
    }

    //滤镜相关组件
    private var mFilterLayout: LinearLayout? = null
    private var mFilterListView: RecyclerView? = null
    private var mFilterAdapter: FilterAdapter? = null

    //边框相关组件

    private var mFrameLayout: LinearLayout? = null
    private var mFrameListView: RecyclerView? = null
    private var mFrameAdapter: FrameAdapter? = null

    private var isRecording = false
    private val MODE_PIC = 1
    private val MODE_VIDEO = 2
    private var mode = MODE_PIC
    private var btn_shutter: ImageView? = null
    private var btn_mode: ImageView? = null
    private var animator: ObjectAnimator? = null
    private var currentFrameInfo: FrameInfo? = null
    private var currentFilterType: MagicFilterType? = null
    private val types = arrayOf(
            MagicFilterType.NONE,//原图
            MagicFilterType.MONO,//单色
            MagicFilterType.COOL,//冷色
            MagicFilterType.FAIRYTALE,//童话
            MagicFilterType.SUNSET,//日落
            MagicFilterType.WHITECAT,//白描
            MagicFilterType.BLACKCAT,
            MagicFilterType.HEALTHY
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_camera)
        MagicEngine.Builder().build(findViewById<View>(R.id.glsurfaceview_camera) as MagicCameraView)
        initView()
        initEvent()
    }


    private fun initView() {
        mFilterLayout = findViewById<View>(R.id.layout_filter) as LinearLayout
        mFilterListView = findViewById<View>(R.id.filter_listView) as RecyclerView

        mFrameLayout = findViewById<View>(R.id.layout_frame) as LinearLayout
        mFrameListView = findViewById<View>(R.id.frame_listView) as RecyclerView

        btn_shutter = findViewById<View>(R.id.btn_camera_shutter) as ImageView
        btn_mode = findViewById<View>(R.id.btn_camera_mode) as ImageView

        initFilterView()
        initFrameView()
        initAnim()
        initCamera()
    }

    @SuppressLint("ObjectAnimatorBinding")
    private fun initAnim() {
        //设置展示滤镜的动画
        animator = ObjectAnimator.ofFloat(btn_shutter, "rotation", 0f, 360f)
        animator?.duration = 500
        animator?.repeatCount = ValueAnimator.INFINITE
    }


    /**
     * 设置相机参数
     */
    private fun initCamera() {
        val screenSize = Point()
        windowManager.defaultDisplay.getSize(screenSize)
        //cameraView 相机的图片的预览组件，其是一个GLSurfaceView view，用于接收opengl处理后的图像数据，展示给用户看
        val cameraView = glsurfaceview_camera as MagicCameraView

        //按照16：9的方式设置预览view的大小
        val params = cameraView.layoutParams as RelativeLayout.LayoutParams
        params.width = screenSize.x
        params.height = screenSize.x / 9 * 16
        iv_frame.layoutParams?.apply {
            width = params.width
            height = params.height
        }
        cameraView.layoutParams = params


        val options = BitmapFactory.Options()
        options.inPreferredConfig = Bitmap.Config.ARGB_8888;
        //拍摄照片成功时，在保存照片到相册前会调用这个回调函数
        cameraView.pictureHandlerCall = object : MagicCameraView.PictureHandlerCall {
            override fun preHandlerForSavePicture(bitmap: Bitmap?): Bitmap? {
                var tempBitmap = bitmap

//                tempBitmap?.let {
//                    if (it.width < it.height) {
//                        tempBitmap = BitmapUtils.rotaingImageView(90, it)
//                    }
//                }


                //如果当前选择了相关的边框，则将边框图片转换为bitmap后与拍摄的照片的bitmap进行合成操作。这样最终拍摄到的图片就带上了边框效果
                return if (currentFrameInfo?.localFileUrl?.isNotEmpty() == true) {
                    //加载边框图片为bitmap
                    val themeBitMap = BitmapFactory.decodeFile(currentFrameInfo!!.localFileUrl, options)
                    BitmapUtils.mergeBitmap(tempBitmap, themeBitMap)
                } else {
                    tempBitmap
                }
            }

        }

    }

    /**
     * 初始化滤镜选择列表
     */
    private fun initFilterView() {
        val linearLayoutManager = LinearLayoutManager(this)
        linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
        mFilterListView!!.layoutManager = linearLayoutManager
        mFilterAdapter = FilterAdapter(this, types)
        mFilterListView!!.adapter = mFilterAdapter
        mFilterAdapter?.setOnFilterChangeListener(object : FilterAdapter.OnFilterChangeListener{
            override fun onFilterChanged(filterType: MagicFilterType?) {
                //点击滤镜项回调，更新相机引擎的滤镜模式
                currentFilterType = filterType
                MagicEngine.getInstance()?.setFilter(filterType)
            }
        })

    }

    /**
     * 初始化边框选择列表
     */
    @SuppressLint("CheckResult")
    private fun initFrameView() {
        val linearLayoutManager = LinearLayoutManager(this)
        linearLayoutManager.orientation = LinearLayoutManager.HORIZONTAL
        mFrameListView?.layoutManager = linearLayoutManager


        //发送网络请求，获取存储在七牛云的边框配置文件data_new.json
        RetrofitServiceManager.getInstance().creat(ApiService::class.java)
                .frameList
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .map {
                    val temp = mutableListOf<FrameInfo>()
                    val none = FrameInfo()
                    none.name = "None"
                    val hasDownloadFiles = getHasDownloadFiles()
                    temp.add(0, none)
                    it.imageList?.map { info ->
                        //判断配置的边框是否已经下载至本地
                        val filename = info.url.substring(info.url.lastIndexOf("/") + 1, info.url.length)
                        hasDownloadFiles?.forEach { file ->
                            if (file.name == filename) {
                                info.hasDownload = true
                                info.localFileUrl = file.absolutePath
                                return@forEach
                            }
                        }

                        temp.add(info)
                    }
                    temp
                }
                .observeOn(AndroidSchedulers.mainThread())

                .subscribe({
                    //将数据设置给数据适配器
                    mFrameAdapter = FrameAdapter(this@CameraActivity, it)
                    mFrameListView?.adapter = mFrameAdapter
                    mFrameAdapter?.setOnFrameChangeListener(object : FrameAdapter.OnFrameChangeListener {
                        override fun onFrameChanged(info: FrameInfo, position: Int) {
                            if (position == 0) {
                                iv_frame.visibility = View.GONE
                            } else {
                                iv_frame.visibility = View.VISIBLE

                                Glide.with(iv_frame.context).load(File(info.localFileUrl)).into(iv_frame)
                            }
                            currentFrameInfo = info

                        }

                    })
                }, {})


    }

    private fun getHasDownloadFiles(): Array<File>? {
        val file = File("/data/data/" + this.packageName.toString() + "/frames")
        if (file.exists()) {
            return file.listFiles()
        }
        return null
    }

    /**
     * 设置按钮的监听器
     */
    private fun initEvent() {
        btn_camera_filter.setOnClickListener {
            //选择滤镜
            showFilters()
        }

        btn_camera_beauty.setOnClickListener {
            //点击选择边框
            showFrame()

        }

        //切换相机模式
        btn_camera_mode.setOnClickListener {
            switchMode()
        }
        //拍照或者录屏
        btn_camera_shutter.setOnClickListener {
            updateCameraMode()
        }

        btn_camera_switch.setOnClickListener {
            MagicEngine.getInstance()?.switchCamera()
        }
        btn_camera_closefilter.setOnClickListener {
            hideFilters()
        }
        //关闭边框选择页
        btn_camera_closeframe.setOnClickListener {
            hideFrame()
        }
    }

    //拍照获取录像
    private fun updateCameraMode() {
        if (mode == MODE_PIC) takePhoto() else takeVideo()
    }

    //切换相机模式
    private fun switchMode() {
        if (mode == MODE_PIC) {
            mode = MODE_VIDEO
            btn_mode!!.setImageResource(R.drawable.icon_camera)
            Toast.makeText(this, "Switch to screen recording mode", Toast.LENGTH_SHORT).show()
//            iv_frame.visibility = View.GONE
//            btn_camera_beauty.visibility = View.INVISIBLE
//            btn_camera_beauty.isClickable = false
//            hideFrame()

        } else {
            mode = MODE_PIC
            btn_mode!!.setImageResource(R.drawable.icon_video)
            Toast.makeText(this, "Switch to screen camera mode", Toast.LENGTH_SHORT).show()
//            btn_camera_beauty.visibility = View.VISIBLE
//            btn_camera_beauty.isClickable = true
//
//            //没有选择滤镜，尝试回复边框
//            if (currentFrameInfo?.localFileUrl?.isNotEmpty() == true) {
//                iv_frame.visibility = View.VISIBLE
//            }

        }
    }

    private var disposable: Disposable? = null
    private var disposableMovies: Disposable? = null

    //配置照片
    private fun takePhoto() {
        disposable?.dispose()
        disposable = createOutputMediaFile().subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe({ outputMediaFile ->
                    MagicEngine.getInstance()?.savePicture(outputMediaFile, object : SavePictureTask.OnPictureSaveListener{
                        override fun onSaved(result: String?) {
                            runOnUiThread { Toast.makeText(this@CameraActivity, "Shooting success", Toast.LENGTH_SHORT).show() }
                        }
                    })
                }, {
                    Log.e(TAG, "takePhoto error", it)
                })
    }

    private fun takeVideo() {
        if (isRecording) {
            animator?.end()
            MagicEngine.getInstance()?.stopRecord()
            Toast.makeText(this, "stop record", Toast.LENGTH_SHORT).show()
        } else {
            animator?.start()
            disposableMovies?.dispose()
            disposableMovies = createOutputMediaMovieFile().subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe({ outputMediaFile ->
                        MagicEngine.getInstance()?.startRecord(outputMediaFile)
                        Toast.makeText(this, "start record", Toast.LENGTH_SHORT).show()
                    }, {
                        Log.e(TAG, "takePhoto error", it)
                    })


        }
        isRecording = !isRecording
    }


    private fun showFilters() {
        mFilterLayout?.let {
            show(it)
        }
    }

    private fun hideFilters() {
        mFilterLayout?.let {
            hide(it)
        }
    }

    private fun showFrame() {
        mFrameLayout?.let {
            show(it)
        }
    }

    private fun hideFrame() {
        mFrameLayout?.let {
            hide(it)
        }
    }

    private fun show(view: View) {
        val animator = ObjectAnimator.ofFloat(view, "translationY", view.height.toFloat(), 0f)
        animator.duration = 200
        animator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
                findViewById<View>(R.id.btn_camera_shutter).isClickable = false
                view.visibility = View.VISIBLE
            }

            override fun onAnimationRepeat(animation: Animator) {}
            override fun onAnimationEnd(animation: Animator) {}
            override fun onAnimationCancel(animation: Animator) {}
        })
        animator.start()
    }


    private fun hide(view: View) {
        if (view.visibility == View.INVISIBLE) {
            return
        }
        val animator = ObjectAnimator.ofFloat(view, "translationY", 0f, view.height.toFloat())
        animator.duration = 200
        animator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator) {
            }

            override fun onAnimationRepeat(animation: Animator) {
            }

            override fun onAnimationEnd(animation: Animator) {
                view.visibility = View.INVISIBLE
                btn_camera_shutter.isClickable = true
            }

            override fun onAnimationCancel(animation: Animator) {
                view.visibility = View.INVISIBLE
                btn_camera_shutter.isClickable = true
            }
        })
        animator.start()
    }

    //生成一个文件，用于存储拍摄的摘片
    private fun createOutputMediaFile(): Single<File> {

        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINESE).format(Date())
        return Single.just(timeStamp)
                .flatMap {
                    //在相册目录下生成文件，这样保存的文件就可以在相册里面看到了
                    val mediaStorageDir = File(Environment.getExternalStoragePublicDirectory(
                            Environment.DIRECTORY_PICTURES), "EasyCamera")
                    if (!mediaStorageDir.exists() && !mediaStorageDir.mkdir()) {
                        Single.error(RuntimeException("picture create fail"))
                    } else {
                        Single.just(File(mediaStorageDir.path + File.separator +
                                "IMG_" + it + ".jpg"))
                    }
                }

    }

    private fun createOutputMediaMovieFile(): Single<File> {

        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.CHINESE).format(Date())
        return Single.just(timeStamp)
                .flatMap {
                    //在相册目录下生成文件，这样保存的文件就可以在相册里面看到了
                    val mediaStorageDir = File(Environment.getExternalStoragePublicDirectory(
                            Environment.DIRECTORY_PICTURES), "EasyCamera")
                    if (!mediaStorageDir.exists() && !mediaStorageDir.mkdir()) {
                        Single.error(RuntimeException("picture create fail"))
                    } else {
                        Single.just(File(mediaStorageDir.path + File.separator + it + ".mp4"))
                    }
                }

    }
}